import rough from "roughjs";
import { Config, Drawable } from "roughjs/bin/core";
import { renderToDrawables } from "./drawing";
import { VNode } from "./vnode";

/**
 * The render configs.
 * 
 * @alpha
 */
export type RenderConfig = {
  clear?: boolean;
  rough?: Config;
};

/**
 * Render the virtuanl nodes and mounted to given element.
 *
 * @param node - the virtual nodes.
 * @param el - the element (or css selector string) to draw on.
 * @public
 */
export function render(
  node: VNode | VNode[],
  el: string | HTMLCanvasElement | SVGSVGElement,
  config?: RenderConfig
) {
  const drawables = renderToDrawables(
    Array.isArray(node) ? node : [node],
    config?.rough
  );
  const element = typeof el === "string" ? document.querySelector(el) : el;
  if (element instanceof HTMLCanvasElement) {
    return renderToCanvas(drawables, element, config);
  }
  if (element instanceof SVGSVGElement) {
    return renderToSvg(drawables, element, config);
  }
  throw new Error("unexpected element to render");
}

function renderToSvg(
  drawables: Drawable[],
  el: SVGSVGElement,
  config?: RenderConfig
) {
  if (config?.clear) {
    el.childNodes.forEach((c) => c.remove());
  }
  const rc = rough.svg(el, config?.rough);
  drawables.forEach((drawable) => {
    el.appendChild(rc.draw(drawable));
  });
}

function renderToCanvas(
  drawables: Drawable[],
  el: HTMLCanvasElement,
  config?: RenderConfig
) {
  if (config?.clear) {
    el.getContext("2d")?.clearRect(0, 0, el.width, el.height);
  }
  const rc = rough.canvas(el, config?.rough);
  drawables.forEach((drawable) => {
    rc.draw(drawable);
  });
}
